// RecordDlg.cpp : implementation file
//

#pragma warning(disable:4786)

#include "stdafx.h"
#include "RMSTranslator.h"
#include "RMSTranslatorDlg.h"
#include "RecordDlg.h"
#include "AddCameraDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CRecordDlg dialog
#define GET_SERVER_DLG			((CRMSTranslatorDlg*)AfxGetMainWnd())
#define GET_BASE_SERVER			(GET_SERVER_DLG->m_Server)
#define getHomePath				GET_SERVER_DLG->getHomePath
#define saveHomePath			GET_SERVER_DLG->saveHomePath

#define TIMER_FREE_SPACE	9998
#define TIMER_CHANGE_DATA	9999

#define MIN_FREE_SPACE 0x5

#define	PACKET_COUNT 255

RecordCamera::RecordCamera()
{
	m_file = NULL;

	m_strFile = "";
	m_strPrevDate = "";

	m_nCameraID = -1;

	m_fps = 0;
	m_nCurrentFrameRate = 0;
	m_nStoredFrameRate = 0;
	m_nFrameRate = 0;
	m_nStoredBitrate = 0;
	m_nFileSize = 0;
	m_lTotalStoredData = 0;

	m_timeStart = 0;
	m_timeEnd = 0;
	m_dwDelta = 0;

	m_pData = new BYTE[0x200000];
	m_pAudio = new BYTE[0x20000];
	m_byPacketCounter = 0;
}

RecordCamera::~RecordCamera()
{
	if(m_pData) delete[] m_pData;
	if(m_pAudio) delete[] m_pAudio;
}

void RecordCamera::ResetData()
{
	pSzAudio=GET_BASE_SERVER.GetDataPtr_SizeAudio(m_nCameraID);
	dtAudio=GET_BASE_SERVER.GetDataPtr_dtAudio(m_nCameraID);
	pCriticalAudio=GET_BASE_SERVER.GetDataPtr_CriticalAudio(m_nCameraID);

	pSzVideo=GET_BASE_SERVER.GetDataPtr_SizeVideo(m_nCameraID);
	dtVideo=GET_BASE_SERVER.GetDataPtr_dtVideo(m_nCameraID);
	pSzDate=GET_BASE_SERVER.GetDataPtr_SizeDate(m_nCameraID);
	dtDate=GET_BASE_SERVER.GetDataPtr_dtDate(m_nCameraID);
	pSzTime=GET_BASE_SERVER.GetDataPtr_SizeTime(m_nCameraID);
	dtTime=GET_BASE_SERVER.GetDataPtr_dtTime(m_nCameraID);
	pCriticalData=GET_BASE_SERVER.GetDataPtr_CriticalData(m_nCameraID);
}

CRecordDlg::CRecordDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRecordDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CRecordDlg)
	m_strDiskSpace = _T("");
	m_strBitrate = _T("");
	m_strCurFrameRate = _T("");
	m_strFileName = _T("");
	m_strFileSize = _T("");
	m_strNewFrameRate = _T("");
	//}}AFX_DATA_INIT
	ASSERT(pParent != NULL);

	m_pParent = pParent;
	m_nID = CRecordDlg::IDD;

	m_bSpace = FALSE;

#ifdef _JNC_REC_
	CString name = getHomePath();
	name += "\\"; name += RECORD_LOG_FNAME;
	recordLog.startLogging(name);
#endif //def _JNC_REC_
}

#ifdef _JNC_REC_
CRecordDlg::~CRecordDlg()
{
	recordLog.stopLogging();
}
#endif //def _JNC_REC_


void CRecordDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRecordDlg)
	DDX_Control(pDX, IDC_NEWFRAMERATE, m_editNewFrameRate);
	DDX_Control(pDX, IDOK, m_btnUpdate);
	DDX_Control(pDX, IDC_RECORDCAMERA, m_listCameras);
	DDX_Text(pDX, IDC_DISKSPACE, m_strDiskSpace);
	DDX_Text(pDX, IDC_BITRATE, m_strBitrate);
	DDX_Text(pDX, IDC_CURFRAMERATE, m_strCurFrameRate);
	DDX_Text(pDX, IDC_FILENAME, m_strFileName);
	DDX_Text(pDX, IDC_FILESIZE, m_strFileSize);
	DDX_Text(pDX, IDC_NEWFRAMERATE, m_strNewFrameRate);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CRecordDlg, CDialog)
	//{{AFX_MSG_MAP(CRecordDlg)
	ON_BN_CLICKED(IDOK, OnUpdate)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_ADDCAMERA, OnAddCamera)
	ON_BN_CLICKED(IDC_DELETE, OnDelete)
	ON_LBN_SELCHANGE(IDC_RECORDCAMERA, OnSelchangeRecordCamera)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRecordDlg message handlers

BOOL CRecordDlg::CreateDlg() 
{
	return CDialog::Create(m_nID, m_pParent);
}

void CRecordDlg::OnUpdate() 
{
	UpdateData(TRUE);
	
	CString strCameraIP;
	int nLen;
	int nCur = m_listCameras.GetCurSel();
	if(nCur == LB_ERR)
	{
		return;
	}

	nLen = m_listCameras.GetTextLen(nCur);
	m_listCameras.GetText(nCur, strCameraIP.GetBuffer(nLen));
	strCameraIP.ReleaseBuffer();

	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera)
		{
			if((*pCamera)->m_strCameraIP == strCameraIP)
			{
				KillTimer((*pCamera)->m_nCameraID);

				(*pCamera)->m_nFrameRate = atoi(static_cast<LPCTSTR>(m_strNewFrameRate));

				SetTimer((*pCamera)->m_nCameraID, 1000/(*pCamera)->m_nFrameRate, 0);
				break;
			}
		}
	}
}

BOOL CRecordDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();

	if(!CheckFreeSpace())
	{
		MessageBox("Warning! Hard disk is full.", "RMS Server", MB_OK | MB_ICONWARNING);

		GET_BASE_SERVER.SetRecordState(FALSE);
		
		GET_SERVER_DLG->SetDlgItemText(IDC_RECORD,"Record");
		m_bSpace = FALSE;
		return FALSE;
	}

	m_bSpace = TRUE;
	
	SetTimer(TIMER_FREE_SPACE, 15000, 0);
	SetTimer(TIMER_CHANGE_DATA, 1000, 0);

	m_btnUpdate.EnableWindow(FALSE);
	m_editNewFrameRate.EnableWindow(FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CRecordDlg::PostNcDestroy() 
{
	Clear();

	delete this;	
}

void CRecordDlg::Clear()
{
	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera)
		{
			DeleteCamera(static_cast<LPCTSTR>((*pCamera)->m_strCameraIP));
			if((*pCamera)->m_file)
			{
				fclose((*pCamera)->m_file);
				(*pCamera)->m_file = NULL;
#ifdef _JNC_REC_
				CString oldname = getHomePath();
				oldname += "\\";
				CString newname = oldname;
				CString name = (LPCTSTR)(*pCamera)->m_strFile;
				oldname += name;
				name += ((*pCamera)->m_tm).toJNCString();
				newname += name;

				recordLog.message("%s%s", name, "");

				oldname += ".rms"; newname += ".rms";
				rename(oldname, newname);
#endif //def _JNC_REC_
			}
			KillTimer((*pCamera)->m_nCameraID);
			delete *pCamera;
			*pCamera = NULL;
		}
	}

	m_listRecordCameras.clear();
}

BOOL CRecordDlg::CheckFreeSpace()
{
	int nTotalFreeSpace;

	if(GetCurrentDirectory(255, m_szBuffer))
	{
		FARPROC pGetDiskFreeSpaceEx = GetProcAddress( GetModuleHandle("kernel32.dll"),
								 "GetDiskFreeSpaceExA");

		if(pGetDiskFreeSpaceEx)
		{
			if(GetDiskFreeSpaceEx(m_szBuffer,
						(PULARGE_INTEGER)&m_i64FreeBytesToCaller,
						(PULARGE_INTEGER)&m_i64TotalBytes,
						(PULARGE_INTEGER)&m_i64FreeBytes))
			{
				nTotalFreeSpace = (int) (m_i64FreeBytesToCaller / (1024 * 1024));
				m_strDiskSpace.Format("%d",nTotalFreeSpace);
			}
			else
			{
				m_strDiskSpace = _T("not defined");
			}
		}
		else
		{
			if(GetDiskFreeSpace (NULL, 
						&m_dwSectPerClust, 
						&m_dwBytesPerSect,
						&m_dwFreeClusters, 
						&m_dwTotalClusters))
			{
				nTotalFreeSpace = (int) (m_dwSectPerClust * m_dwBytesPerSect * m_dwFreeClusters / (1024 * 1024));
				m_strDiskSpace.Format("%d",nTotalFreeSpace);
			}
			else
			{
				m_strDiskSpace = _T("not defined");
			}
		}
	}
	else
	{
		if(GetDiskFreeSpace (NULL, 
					&m_dwSectPerClust, 
					&m_dwBytesPerSect,
					&m_dwFreeClusters, 
					&m_dwTotalClusters))
		{
			nTotalFreeSpace = (int) (m_dwSectPerClust * m_dwBytesPerSect * m_dwFreeClusters / (1024 * 1024));
			m_strDiskSpace.Format("%d",nTotalFreeSpace);
		}
		else
		{
			m_strDiskSpace = _T("not defined");
		}
	}

	UpdateData(FALSE);

	if((nTotalFreeSpace < MIN_FREE_SPACE) && nTotalFreeSpace)
	{
		return FALSE;
	}

	return TRUE;
}

BOOL CRecordDlg::CheckStartCamera(int nCameraID)
{
	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera)
		{
			if((*pCamera)->m_nCameraID == nCameraID)
			{
				return TRUE;
			}
		}
	}

	return FALSE;
}

void CRecordDlg::DeleteCamera(const char* szCameraIP)
{
	if(szCameraIP)
	{
		int n = m_listCameras.FindString(-1,szCameraIP);
		if(n != LB_ERR)
		{
			m_listCameras.DeleteString(n);
			UpdateCameraInfo(TRUE);
		}
	}
}

void CRecordDlg::OnTimer(UINT nIDEvent) 
{
	UpdateData(TRUE);
	switch(nIDEvent)
	{
	case TIMER_FREE_SPACE:
		if(!CheckFreeSpace())
		{
			KillTimer(TIMER_FREE_SPACE);
			KillTimer(TIMER_CHANGE_DATA);

			MessageBox("Warning! Hard disk is full.", "RMS Server", MB_OK | MB_ICONWARNING);

			GET_BASE_SERVER.SetRecordState(FALSE);
			
			GET_SERVER_DLG->SetDlgItemText(IDC_RECORD,"Record");
			EndDialog(IDOK);
		}
		break;
	case TIMER_CHANGE_DATA:
		UpdateCameraInfo();
		break;
	default:
		SaveCameraData(nIDEvent);
		break;
	}
	
	CDialog::OnTimer(nIDEvent);
}

void CRecordDlg::OnCancel() 
{
	GET_BASE_SERVER.SetRecordState(FALSE);
	GET_SERVER_DLG->SetDlgItemText(IDC_RECORD,"Record");
	
	Clear();

	CDialog::OnCancel();
}

void CRecordDlg::OnAddCamera() 
{
	CAddCameraDlg dlg;
	if(dlg.DoModal() == IDOK)
	{
		if(dlg.m_nCameraID > 0)
		{
			if(CheckStartCamera(dlg.m_nCameraID))
			{
				return;
			}

			CInfo info;
			GET_BASE_SERVER.GetCameraInfo(dlg.m_nCameraID, info);

			if(GET_BASE_SERVER.CheckStartCamera(dlg.m_nCameraID) < 0)
			{
				return;
			}
			RecordCamera* pCamera = new RecordCamera;
			pCamera->m_nCameraID = dlg.m_nCameraID;
			pCamera->m_strCameraIP = info.m_ip;
			pCamera->m_nFrameRate = 10;

			pCamera->ResetData();

			m_listRecordCameras.push_back(pCamera);

			m_listCameras.SetCurSel(m_listCameras.AddString(static_cast<LPCTSTR>(info.m_ip)));
			UpdateCameraInfo(TRUE);

			SetTimer(pCamera->m_nCameraID, 1000/pCamera->m_nFrameRate, 0);
		}
	}	
}

void CRecordDlg::UpdateCameraInfo(BOOL bChangeCamera)
{
	HANDLE hFile; 
	CString strCameraIP;
	int nLen;
	int nCur = m_listCameras.GetCurSel();

	if(!UpdateData(TRUE))
	{
		return;
	}

	if(nCur == LB_ERR)
	{
		m_strFileName = "none";
		m_strBitrate = "none";
		m_strCurFrameRate = "none";
		m_strFileSize = "none";

		m_btnUpdate.EnableWindow(FALSE);
		m_editNewFrameRate.EnableWindow(FALSE);

		UpdateData(FALSE);
		return;
	}

	m_btnUpdate.EnableWindow(TRUE);
	m_editNewFrameRate.EnableWindow(TRUE);

	nLen = m_listCameras.GetTextLen(nCur);
	m_listCameras.GetText(nCur, strCameraIP.GetBuffer(nLen));
	strCameraIP.ReleaseBuffer();

	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera)
		{
			if((*pCamera)->m_strCameraIP == strCameraIP)
			{
				CString hp = (LPCTSTR)(*pCamera)->m_strFile; hp += ".rms";
				m_strFileName = hp;
				m_strBitrate.Format("%d",(*pCamera)->m_nStoredBitrate);
				m_strCurFrameRate.Format("%d",(*pCamera)->m_nStoredFrameRate);
				m_strFileSize.Format("%d",(*pCamera)->m_nFileSize);

				if(bChangeCamera)
				{
					m_strNewFrameRate.Format("%d",(*pCamera)->m_nFrameRate);
				}

				hp = getHomePath();
				hp += "\\"; hp += (LPCTSTR)(*pCamera)->m_strFile; hp += ".rms";
				hFile = CreateFile(hp,
								0/*GENERIC_READ*/,              // open for reading 
								0/*FILE_SHARE_READ*/,           // share for reading 
								NULL,                      // no security 
								OPEN_EXISTING,             // existing file only 
								FILE_ATTRIBUTE_NORMAL,     // normal file 
								NULL);                     // no attr. template 

				(*pCamera)->m_nFileSize = 0;
				if (hFile != INVALID_HANDLE_VALUE) 
				{ 
					DWORD dwFileSize;

					dwFileSize = GetFileSize(hFile, NULL);
					if((int)dwFileSize != -1)
					{
						(*pCamera)->m_nFileSize = (int)((float)(dwFileSize) / (1024.0*1024.0) + .5);
					}
					CloseHandle(hFile);
				}

				if((*pCamera)->m_nFileSize)
				{
					m_strFileSize.Format("%d",(*pCamera)->m_nFileSize);
				}
				else
				{
					m_strFileSize = _T("0");
				}
				break;
			}
		}
	}
	UpdateData(FALSE);
}

void CRecordDlg::OnDelete() 
{
	CString strCameraIP;
	int nLen;
	int nCur = m_listCameras.GetCurSel();
	if(nCur == LB_ERR)
	{
		return;
	}

	nLen = m_listCameras.GetTextLen(nCur);
	m_listCameras.GetText(nCur, strCameraIP.GetBuffer(nLen));
	strCameraIP.ReleaseBuffer();

	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera)
		{
			if((*pCamera)->m_strCameraIP == strCameraIP)
			{
				if((*pCamera)->m_file)
				{
					fclose((*pCamera)->m_file);
					(*pCamera)->m_file = NULL;
#ifdef _JNC_REC_
					CString oldname = getHomePath();
					oldname += "\\";
					CString newname = oldname;
					CString name = (LPCTSTR)(*pCamera)->m_strFile;
					oldname += name;
					name += ((*pCamera)->m_tm).toJNCString();
					newname += name;

					recordLog.message("%s%s", name, "");

					oldname += ".rms"; newname += ".rms";
					rename(oldname, newname);
#endif //def _JNC_REC_
				}
				KillTimer((*pCamera)->m_nCameraID);
				delete *pCamera;
				*pCamera = NULL;
			}
		}
	}
	m_listRecordCameras.remove(NULL);

	DeleteCamera(static_cast<LPCTSTR>(strCameraIP));
}

void CRecordDlg::OnSelchangeRecordCamera() 
{
	UpdateCameraInfo(TRUE);
}

void CRecordDlg::SaveCameraData(int nCameraID)
{
	DWORD dwLen, dwTag;
	int nTimeSize;
	int nDateSize;
	int nDataSize;

	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera)
		{
			if((*pCamera)->m_nCameraID == nCameraID)
			{
				EnterCriticalSection((*pCamera)->pCriticalData);

				memcpy((*pCamera)->m_pData, (*pCamera)->dtVideo, *(*pCamera)->pSzVideo);
				nDataSize = *(*pCamera)->pSzVideo;
				memcpy((*pCamera)->m_szDate, (*pCamera)->dtDate, *(*pCamera)->pSzDate);
				nDateSize = *(*pCamera)->pSzDate;
				memcpy((*pCamera)->m_szTime, (*pCamera)->dtTime, *(*pCamera)->pSzTime);
				nTimeSize = *(*pCamera)->pSzTime;

				LeaveCriticalSection((*pCamera)->pCriticalData);

				if(nDataSize && nTimeSize && nDateSize)
				{
					int y, m, d, h, mi, s;

					GetDate((*pCamera)->m_szDate, d, m, y);
					GetTime((*pCamera)->m_szTime, s, mi, h);
					(*pCamera)->m_tm.dwYear = y;
					(*pCamera)->m_tm.bMonth = m;
					(*pCamera)->m_tm.bDay = d;
					(*pCamera)->m_tm.bHour = h;
					(*pCamera)->m_tm.bMinute = mi;
					(*pCamera)->m_tm.bSecond = s;

					(*pCamera)->m_lockFile.Lock();
					if(!(*pCamera)->m_file)
					{
#ifdef _JNC_REC_
						(*pCamera)->m_strFile.Format("%d-%s-", nCameraID, ((*pCamera)->m_tm).toJNCString());
#else //def _JNC_REC_
						GetFileName((*pCamera)->m_szDate, (*pCamera)->m_nCameraID, (*pCamera)->m_strFile);
#endif //def _JNC_REC_

						CString hp = getHomePath();
						hp += "\\"; hp += (LPCTSTR)(*pCamera)->m_strFile; hp += ".rms";
						(*pCamera)->m_file = fopen(hp, "ab");
						if(!(*pCamera)->m_file) { (*pCamera)->m_lockFile.Unlock(); return; }
					}
#ifndef _JNC_REC_
					if((*pCamera)->m_strPrevDate != "")
					{
						if(strcmp((*pCamera)->m_szDate, static_cast<LPCTSTR>((*pCamera)->m_strPrevDate)) != 0)
						{
							fclose((*pCamera)->m_file);
							(*pCamera)->m_file = NULL;

							GetFileName((*pCamera)->m_szDate, (*pCamera)->m_nCameraID, (*pCamera)->m_strFile);

							CString hp = getHomePath();
							hp += "\\"; hp += (LPCTSTR)(*pCamera)->m_strFile; hp += ".rms";
							(*pCamera)->m_file = fopen(hp, "ab");
							if(!(*pCamera)->m_file) { (*pCamera)->m_lockFile.Unlock(); return; }
						}
					}
#endif //ndef _JNC_REC_
					(*pCamera)->m_lockFile.Unlock();

					(*pCamera)->m_strPrevDate = (*pCamera)->m_szDate;

					(*pCamera)->m_timeEnd = timeGetTime();
					(*pCamera)->m_dwDelta = (*pCamera)->m_dwDelta + ((*pCamera)->m_timeEnd - (*pCamera)->m_timeStart);

					if((*pCamera)->m_timeEnd - (*pCamera)->m_timeStart)
					{
						(*pCamera)->m_nCurrentFrameRate = (int)((1000.0)/(float)((*pCamera)->m_timeEnd - (*pCamera)->m_timeStart) + 0.5);
					}
					else
					{
						(*pCamera)->m_nCurrentFrameRate = 0;
					}

					(*pCamera)->m_timeStart = timeGetTime();

					if((int)((*pCamera)->m_dwDelta) > 1000)
					{
						(*pCamera)->m_nStoredFrameRate = (int)(((float)(*pCamera)->m_fps * 1000.0) / (float)(*pCamera)->m_dwDelta + .5);
						(*pCamera)->m_nStoredBitrate = (int)((((float)(*pCamera)->m_lTotalStoredData * 8.0 / 1024.0) * 1000.0 ) / (float)(*pCamera)->m_dwDelta + .5);
						(*pCamera)->m_fps = 0;
						(*pCamera)->m_dwDelta = 0;
						(*pCamera)->m_lTotalStoredData = 0;
					}
					(*pCamera)->m_fps++;

					dwLen = 0;

					(*pCamera)->m_lockFile.Lock();

					dwTag = TAG_STOREDDATA;
					dwLen += sizeof(DWORD);
					fwrite(&dwTag, sizeof(DWORD), 1, (*pCamera)->m_file);

					dwTag = TAG_TIMEMARK;
					dwLen += sizeof(DWORD);
					fwrite(&dwTag, sizeof(DWORD), 1, (*pCamera)->m_file);

					dwLen += sizeof(TimeMark);
					fwrite(&((*pCamera)->m_tm), sizeof(TimeMark), 1, (*pCamera)->m_file);

					dwTag = TAG_STOREDTIME_v01;
					dwLen += sizeof(DWORD);
					fwrite(&dwTag, sizeof(DWORD), 1, (*pCamera)->m_file);
					dwLen += sizeof(DWORD);
					fwrite(&nTimeSize, sizeof(DWORD), 1, (*pCamera)->m_file);
					dwLen += nTimeSize;
					fwrite((*pCamera)->m_szTime, sizeof(BYTE), nTimeSize, (*pCamera)->m_file);

					dwTag = TAG_STOREDDATE_v01;
					dwLen += sizeof(DWORD);
					fwrite(&dwTag, sizeof(DWORD), 1, (*pCamera)->m_file);
					dwLen += sizeof(DWORD);
					fwrite(&nDateSize, sizeof(DWORD), 1, (*pCamera)->m_file);
					dwLen += nDateSize;
					fwrite((*pCamera)->m_szDate, sizeof(BYTE), nDateSize, (*pCamera)->m_file);

					dwTag = TAG_RMSSTOREDVIDEO_v01;
					dwLen += sizeof(DWORD);
					fwrite(&dwTag, sizeof(DWORD), 1, (*pCamera)->m_file);
					nDataSize += sizeof(int);
					dwLen += sizeof(DWORD);
					dwLen += nDataSize;
					fwrite(&nDataSize, sizeof(DWORD), 1, (*pCamera)->m_file);
					fwrite(&(*pCamera)->m_nCurrentFrameRate,sizeof(int), 1, (*pCamera)->m_file);
					nDataSize -= sizeof(int);
					fwrite((*pCamera)->m_pData, sizeof(BYTE), nDataSize, (*pCamera)->m_file);

					dwTag = TAG_SIZE;
					fwrite(&dwTag, sizeof(DWORD), 1, (*pCamera)->m_file);
					fwrite(&dwLen, sizeof(DWORD), 1, (*pCamera)->m_file);

					fflush((*pCamera)->m_file);
					(*pCamera)->m_lTotalStoredData += dwLen;
					(*pCamera)->m_lockFile.Unlock();
				}

				return;
			}
		}
	}
}

void CRecordDlg::SaveCameraAudio(int nCameraID, BYTE n)
{
	DWORD dwLen, dwTag, dwl;
	int nAudioSize;

	list<RecordCamera*>::iterator pCamera;
	for(pCamera = m_listRecordCameras.begin(); pCamera != m_listRecordCameras.end(); pCamera++)
	{
		if(*pCamera && (*pCamera)->m_file && ((*pCamera)->m_nCameraID == nCameraID))
		{
			EnterCriticalSection((*pCamera)->pCriticalAudio);
			memcpy((*pCamera)->m_pAudio+(2*sizeof(DWORD)+sizeof(BYTE)), (*pCamera)->dtAudio, *(*pCamera)->pSzAudio);
			nAudioSize = *(*pCamera)->pSzAudio;
			LeaveCriticalSection((*pCamera)->pCriticalAudio);

			if(nAudioSize)
			{
				dwTag = TAG_RMSSTOREDSOUND_v01;
				memcpy((*pCamera)->m_pAudio, &dwTag, sizeof(DWORD));
				nAudioSize++;
				memcpy((*pCamera)->m_pAudio+sizeof(DWORD), &nAudioSize, sizeof(DWORD));
				nAudioSize--;
				memcpy((*pCamera)->m_pAudio+(2*sizeof(DWORD)), &n, sizeof(BYTE));
				dwl = nAudioSize + (8 + 1);
				while(nAudioSize)
				{
					nAudioSize -= 33; // could be few audio packets
				}

				(*pCamera)->m_lockFile.Lock();
				fwrite((*pCamera)->m_pAudio, 1, dwl, (*pCamera)->m_file);
				(*pCamera)->m_lTotalStoredData += dwLen;
				(*pCamera)->m_lockFile.Unlock();
			}
			return;
		}
	}
}
